package com.springBoot.springBootSysCore.listener;

import javax.persistence.criteria.*;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.springBoot.springBootSysCore.common.comment.annotation.AddComment;
import com.springBoot.springBootSysCore.common.config.Global;
import com.springBoot.springBootSysCore.common.utils.FileUtil;
import com.springBoot.springBootSysCore.common.utils.ObjectUtils;
import com.springBoot.springBootSysCore.common.utils.SpringContextHolder;
import com.springBoot.springBootSysCore.common.utils.encoding.Encodes;
import com.springBoot.springBootSysCore.common.utils.json.JsonUtil;
import com.springBoot.springBootSysCore.modules.entity.system.SysFileTmp;
import com.springBoot.springBootSysCore.modules.entity.system.SysResource;
import com.springBoot.springBootSysCore.modules.entity.system.SysRole;
import com.springBoot.springBootSysCore.modules.entity.system.SysUser;
import com.springBoot.springBootSysCore.modules.enums.base.DeleteStateEnum;
import com.springBoot.springBootSysCore.modules.enums.base.UserTypeEnum;
import com.springBoot.springBootSysCore.modules.repository.system.SysFileTmpRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysResourceRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysRoleRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysUserRepository;
import com.springBoot.springBootSysCore.modules.services.SystemService;
import com.springBoot.springBootSysCore.modules.services.system.SysResourceService;
import com.springBoot.springBootSysCore.modules.shiro.ShiroFilerChainManager;
import net.sf.json.util.JSONUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.io.*;
import java.net.URLDecoder;
import java.util.*;


@WebListener
public class IndexListener implements ServletContextListener {
    private Log logger = LogFactory.getLog(IndexListener.class);
    @Autowired
    private SysFileTmpRepository sysFileTmpRepository;
    @Autowired
    private SysRoleRepository sysRoleRepository;
    @Autowired
    private SysResourceRepository sysResourceRepository;
    @Autowired
    private SysResourceService sysResourceService;
    @Autowired
    private SysUserRepository sysUserRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private ShiroFilerChainManager shiroFilerChainManager;
    @Autowired
    AddComment addComment;



    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //初始化autowired tomcat运行时必要设置 springboot运行无需
        WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext()).getAutowireCapableBeanFactory().autowireBean(this);

        addComment.addComment();
        try {
            startCleanFileTmp();//清除fileTmp中上传的垃圾文件
        } catch (Exception e) {
        }
        File file = null;
        try {
            //初始化数据
            String javaPath = this.getClass().getResource("/").getFile();
            if(javaPath.indexOf("target")>0){
                javaPath = javaPath.substring(0,javaPath.indexOf("target"));
                javaPath += "src/main/resources";
            }
            file = new File(URLDecoder.decode(javaPath,"utf-8") + "/initDataRes.txt");
            readResText(file);
            saveResText(file);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("初始化发生异常");
        }
        logger.info("初始化权限");
        shiroFilerChainManager.initFilterChains(sysResourceRepository.findAll());
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
    /**
     * 清除fileTmp中上传的垃圾文件
     */
    @Transactional
    private void startCleanFileTmp() {
        List<SysFileTmp> list = sysFileTmpRepository.findAll(new Specification<SysFileTmp>() {
            @Override
            public Predicate toPredicate(Root<SysFileTmp> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                final Path<String> delFlag = root.get("delFlag");
                List<Predicate> list=new ArrayList<Predicate>();
                list.add(cb.equal(delFlag.as(String.class), DeleteStateEnum.NO_DELETE.getVal()));
                query.where(list.toArray(new Predicate[list.size()]));
                return query.getRestriction();
            }
        });
        for (SysFileTmp fileTmp : list) {
            File file = new File(fileTmp.getPath());
            if(file.exists()){
                FileUtil.deleteFile(fileTmp.getPath());
            }
            sysFileTmpRepository.delete(fileTmp);
        }
    }

    /**
     * 从文件中读取数据到数据库 或者初始化数据
     * 角色 资源 用户
     * @param file
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    @Transactional
    public void readResText(File file) throws JsonParseException, JsonMappingException, IOException{
        List<Map<String, Object>> li = jdbcTemplate.queryForList("select * from SYS_ROLE where id = '1B0E0767851D4EA59AA2EC50E6E79654'");
        if(li.isEmpty()){
            logger.info("没有默认角色,开始插入");
            String sql ="insert into SYS_ROLE(NAME, REMARK,IS_SYSROLE, CODE, CREATE_DATE,ID,del_flag) values (?, ?,?, ?, ?, ?,?)";
            jdbcTemplate.update(sql,  new Object[] {"系统管理员","预留的管理员",1,"ROLE_SYS_ADMIN",new Date(),"1B0E0767851D4EA59AA2EC50E6E79654","0"});
            jdbcTemplate.update(sql,  new Object[] {"普通用户","没有后台权限",1,"ROLE_REGIST_CODE",new Date(),"1B0E0767851D4EA59AA2EC50E6E79653","0"});
        }else{
            logger.info("默认角色已存在-无需初始化");
        }
        SysRole role=sysRoleRepository.findOne("1B0E0767851D4EA59AA2EC50E6E79654");
        if (file.exists()) {// 如果文件存在-导入数据文件
            int rNumber =	sysResourceRepository.findAllCount();
            if(rNumber==0){
                logger.info("开始初始化资源数据");
                List<SysResource> list = JsonUtil.getEntitys(this.txt2String(file), List.class, SysResource.class);
                sysResourceService.initSaveList(list);
                logger.info("初始化管理员权限");
                role.setResources(sysResourceRepository.findAll());
                role=sysRoleRepository.save(role);
            }
        }
        int uNumber = sysUserRepository.findAllCount();
        if(uNumber==0){
            SysUser sysUser = new SysUser();
            sysUser.setAccount("admin");
            sysUser.setCreateDate(new Date());
            sysUser.setNickName("管理员");
            sysUser.setSex(1);
            sysUser.setPassword(SystemService.entryptPassword("admin"));
            sysUser.setDefalutRole(role);
            sysUser.setUserType(UserTypeEnum.ADMIN.getVal());
            sysUser.setActivation(Global.TRUE);
            sysUser.setRemarks("默认管理员用户");
            logger.info("初始化管理员用户");
            sysUserRepository.save(sysUser);
        }
    }
    /**
     * 如果文件不存在--从数据库提取资源数据到文件中
     * @param file
     * @throws IOException
     */
    public void saveResText(File file) throws IOException{
        logger.info("开始验证存储资源数据是否存在");
        FileOutputStream fileOutputStream = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }else{
                logger.info("文件已经存在");
                return;
            }
            List<SysResource> list = sysResourceRepository.findAll();
            fileOutputStream = new FileOutputStream(file);
            byte[] content = JsonUtil.writeValueAsString(list).getBytes("utf-8");
            fileOutputStream.write(content);
            fileOutputStream.flush();
            fileOutputStream.close();
            logger.info("资源数据存储成功");
        } catch (Exception e) {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            logger.info("资源数据存储失败", e);
            e.printStackTrace();
        }
    }
    /**
     * 读取txt文件的内容
     *
     * @param file
     *            想要读取的文件对象
     * @return 返回文件内容
     */
    public static String txt2String(File file) {
        String result = "";
        try {
            InputStreamReader read =new InputStreamReader(new FileInputStream(file), "utf-8");
            BufferedReader br = new BufferedReader(read);
            String s = null;
            while ((s = br.readLine()) != null) {// 使用readLine方法，一次读一行
                result = result + "\n" + s;
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

